/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * All Rights Researved.
 *
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * Description: 
                
 *
 *
 * User: jinchen
 * Date: Jun 7, 2003
 * Time: 1:32:07 PM
 */
package edu.psu.geovista.app.pcp.plot.control;

import edu.psu.geovista.app.pcp.plot.control.tools.*;
import edu.psu.geovista.app.pcp.plot.gui.BasicPcpUI;
import edu.psu.geovista.app.plot.axis.AxisList;
import edu.psu.geovista.app.plot.axis.YAxis;

import javax.swing.event.MouseInputListener;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Iterator;

public class MouseObserver implements  MouseListener,
        MouseMotionListener{
   public static final boolean DEBUG = false;
   public static final int Model_Axis=1;
   public static final int Model_Data=2;
   public static final int Model_Plot=3;

   // 
   // 
   public static final int judgeDistance=5;//pixel. Make judgement on if users want to move axis veritcally or horizontally only after dragging <judgeDistance> pixels


   private int model;
    // AxisOrderTool axt;
   BasicPcpUI ui;
   MouseInputListener listener;

   ToolManager toolsMgr;
   AxisList yaxisList ;
   Point pressPoint=new Point();
   boolean knowIfOrderOrMove=false;//if true, means we know if users want to do reorder or move axis
   DataSelectTool moveListener;
   DefaultMouseTool defaultCmd;

    public MouseObserver() {

    }

    public void setup(BasicPcpUI ui){
        this.ui = ui;
        yaxisList =ui.getPlot().getYaxisList() ;
        toolsMgr=ui.getToolsMgr() ;
       // tooltipMgr=ui.getTooltipMgr();
        this.setListener(null);
    }

    public void mousePressed(MouseEvent e) {

        DefaultMouseTool cmd=getDefaultCmd();
        if(cmd==null)return; //getDefaultCmd()=null => null exception when no data loaded  yet

        cmd.mousePressed(e);

        int x=e.getX() ;
        int y=e.getY() ;
        this.pressPoint.setLocation(x,y);
        if(this.getAxisWhoseFooterContain(x,y)!=null ){ //mouse event happen within an axis's footer => it is an axis operations
            //---> 
            AxisMoveTool axMvCmd=(AxisMoveTool)toolsMgr.getCmd(BasicTool.AxisMoveT );
            AxisShowRangeTool ashCmd=(AxisShowRangeTool)toolsMgr.getCmd(BasicTool.AxisShowRangeT );
            AxisOrderTool axOrdCmd=(AxisOrderTool)toolsMgr.getCmd(BasicTool.AxisOrderT );
            axMvCmd.mousePressed(e);
            ashCmd.mousePressed(e);
            axOrdCmd.mousePressed(e);
            //<---

           if(e.isControlDown() ){// move
                axMvCmd=(AxisMoveTool)toolsMgr.getCmd(BasicTool.AxisMoveT );
                setListener(axMvCmd);
               // this.setKnowIfOrderOrMove(true);
               if(DEBUG){
                    System.out.println("intentsion:move axis");
                }
           }
           else{
            /*AxisOrderCmd axOrdCmd=(AxisOrderCmd)actionControl.getCmd(BasicCmd.AxisOrderT );
            setListener(axOrdCmd);*/
              //this.setKnowIfOrderOrMove(false);
               if(DEBUG)
               System.out.println("Not know intension");
               this.setListener(null);//initial the listener is DataSelectCmd, need remove it
           }

        }
        else{  //it is an data operation: select
            DataSelectTool scmd=(DataSelectTool)toolsMgr.getCmd(BasicTool.DataSelectT );
            setListener(scmd);
            //this.setKnowIfOrderOrMove(true);
            if(DEBUG){
                    System.out.println("intentsion:select");
                }
        }

        if(listener!=null)
        listener.mousePressed(e);

     }
     public void mouseDragged(MouseEvent e) {
         if(this.getListener() ==null/*!this.isKnowIfOrderOrMove()*/ ){//not know it
            int x=e.getX() ;
            int y=e.getY() ;
            //int deltay=
             double deltay = Math.abs(y-this.pressPoint.getY());
             double deltax = Math.abs(x-this.pressPoint.getX() );
             if(DEBUG)
             System.out.println("deltay:deltax:  "+deltay+","+deltax);
             if(deltay>=judgeDistance||deltax>=judgeDistance){
                     if(deltay -deltax>0 ){
                        AxisShowRangeTool ashCmd=(AxisShowRangeTool)toolsMgr.getCmd(BasicTool.AxisShowRangeT );
                        setListener(ashCmd);
                       // this.setKnowIfOrderOrMove(true);
                        if(DEBUG){
                            System.out.println("---> intentsion:updown axis");
                        }
                    }
                    else{
                        if(toolsMgr!=null){
                        AxisOrderTool axOrdCmd=(AxisOrderTool)toolsMgr.getCmd(BasicTool.AxisOrderT );
                        setListener(axOrdCmd);
                        //this.setKnowIfOrderOrMove(true);
                        if(DEBUG){
                            System.out.println("----------------------------------> intentsion:reorder axis");
                        }
                        }
                    }
             }
         }//if

         if(listener!=null)
         listener.mouseDragged(e);
     }
     public void mouseMoved(MouseEvent e) {

         if(listener!=null)
            listener.mouseMoved(e);
        
         //highlight a observation
         DefaultMouseTool defaultCmd = this.getDefaultCmd();
         if(defaultCmd!=null)
            defaultCmd.mouseMoved(e);


       



     }

    public DefaultMouseTool getDefaultCmd() {
      /*  if(defaultCmd==null){*/// 
           if (toolsMgr==null)return null;
            defaultCmd=(DefaultMouseTool) toolsMgr.getCmd(BasicTool.DMouseT );
        /*}*/
        return defaultCmd;
    }

    public DataSelectTool getMoveListener() {
        if(moveListener==null){
            moveListener=(DataSelectTool)toolsMgr.getCmd(BasicTool.DataSelectT );

        }
        return moveListener;
    }

     public void mouseReleased(MouseEvent e) {
         DefaultMouseTool defaultCmd = this.getDefaultCmd();
         if(defaultCmd!=null)
         defaultCmd.mouseReleased(e);
         if(listener!=null)
         listener.mouseReleased(e);
         this.setListener(null);
         //this.setKnowIfOrderOrMove(false);
     }
     /*private MouseInputListener getDefaultListener(){

     }*/


     public void mouseEntered(MouseEvent e) {}
     public void mouseExited(MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {
        //dp{
        if (DEBUG){
            System.out.println("click on:("+e.getX() +","+e.getY() +")");
        }//dp}
        int x=e.getX() ;
        int y=e.getY() ;
        //this.pressPoint.setLocation(x,y);
        if(this.getAxisWhoseFooterContain(x,y)==null ){
            if (toolsMgr!=null) {
                DataSelectTool scmd=(DataSelectTool)toolsMgr.getCmd(BasicTool.DataSelectT );
                setListener(scmd);
                if(listener!=null)
                    listener.mouseClicked(e);
            }
        }


    }

    public MouseInputListener getListener() {
        return listener;
    }

    public void setListener(MouseInputListener listener) {
        this.listener = listener;
    }
    /**
     *
     * @param x
     * @param y
     * @return  an YAxis whose root contain the point(x,y)
     */
    public YAxis getAxisWhoseFooterContain(int x, int y){
        if(yaxisList==null)return null;
        for (Iterator iterator = this.yaxisList.iterator(); iterator.hasNext();) {
            YAxis axis = (YAxis) iterator.next();
            if(axis.footerContain(x,y) )
                return axis;

        }
        return null;
    }


    public void setYaxisList(AxisList yaxisList) {
        this.yaxisList = yaxisList;
    }

   /* public boolean isKnowIfOrderOrMove() {
        return knowIfOrderOrMove;
    }

    public void setKnowIfOrderOrMove(boolean knowIfOrderOrMove) {
        this.knowIfOrderOrMove = knowIfOrderOrMove;
    }*/
}
